/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2010 huliqing, huliqing.cn@gmail.com
 *
 * This file is part of QFaces.
 * QFaces is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * QFaces is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with QFaces.  If not, see <http://www.gnu.org/licenses/>.
 *
 * 这个文件是QFaces的一部分。
 * 您可以单独使用或分发这个文件，但请不要移除这个头部声明信息.
 * QFaces是一个自由软件，您可以自由分发、修改其中的源代码或者重新发布它，
 * 新的任何修改后的重新发布版必须同样在遵守LGPL3或更后续的版本协议下发布.
 * 关于LGPL协议的细则请参考COPYING、COPYING.LESSER文件，
 * 您可以在QFaces的相关目录中获得LGPL协议的副本，
 * 如果没有找到，请连接到 http://www.gnu.org/licenses/ 查看并获取副本。
 *
 * - Author: Huliqing
 * - Contact: huliqing.cn@gmail.com
 * - License: GNU Lesser General Public License (LGPL)
 * - Blog and source code availability: http://www.huliqing.name/
 */

Q.F.UITree = {
	init : function(ID_CLIENT, componentClass, listenerExp, srcClosedLast, srcClosedMiddle, srcOpenedLast, srcOpenedMiddle, srcLeafLast, srcLeafMiddle, srcLink, showRoot, rootName, srcImageDefault, autoInitRoot) {
		var tree = new Q.F.UITree.Tree(ID_CLIENT, componentClass, listenerExp, srcClosedLast, srcClosedMiddle, srcOpenedLast, srcOpenedMiddle, srcLeafLast, srcLeafMiddle, srcLink, showRoot, rootName, srcImageDefault, autoInitRoot);
		Q.F.put(ID_CLIENT, tree);
	}
}
Q.F.UITree.Tree = function(ID_CLIENT, componentClass, listenerExp, srcClosedLast, srcClosedMiddle, srcOpenedLast, srcOpenedMiddle, srcLeafLast, srcLeafMiddle, srcLink, showRoot, rootName, srcImageDefault, autoInitRoot) {
	this.ID_CLIENT = ID_CLIENT;
	this.componentClass = componentClass;
	this.listenerExp = listenerExp;
	this.srcClosedLast = srcClosedLast;
	this.srcClosedMiddle = srcClosedMiddle;
	this.srcOpenedLast = srcOpenedLast;
	this.srcOpenedMiddle = srcOpenedMiddle;
	this.srcLeafLast = srcLeafLast;
	this.srcLeafMiddle = srcLeafMiddle;
	this.srcLink = srcLink;
	this.showRoot = (showRoot == "true" ? true : false);
	this.rootName = rootName,
	this.srcImageDefault = srcImageDefault;
	this.autoInitRoot = (autoInitRoot == "true" ? true : false);
	this.root = null;	// 以节点树的层次形式保存所有节点
	this.nodes = new Array();	// 以数组形式保存所有节点
	
	this.init = function() {
		// init root node
		this.root = new Q.F.UITree.Tree.Node();
		this.root.id = "root";
		this.root.uniqueId = this.ID_CLIENT + ":root";
		this.root.value = this.rootName;
		this.root.leaf = false;
		this.nodes[this.root.getUniqueId()] = this.root;
		var children = new Array();
		children[0] = this.root;
		this.initChildren(null, children);
		// 如果不显示根节点,则隐藏,但是必须先显示出根节点下的子节点
		if (!this.showRoot) {
			this.ajaxInvoke(this.root, this);
			this.openNode(this.root);
			this.hideNodeHeader(this.root);
		}
		// 自动载入根节点的子节点
		if (this.autoInitRoot && !this.root.isLoaded()) {
			this.ajaxInvoke(this.root, this);
			this.openNode(this.root);
		}
	}
	this.initChildren= function(parent, children) {
		if (children == null || children.length <= 0) 
			return;
		var body;
		if (parent) {
			body = Q.get(parent.getUniqueId() + ":body:1");
		} else { // RootNode
			body = Q.get(this.ID_CLIENT);
		}
		for (var i = 0; i < children.length; i++) {
			body.appendChild(this.createNodeElement(children[i]))
		}
	}
	/**
	 * 节点node - nodeId (header, body)
	 * header - nodeId:header (nodeId:header:flag, nodeId:header:img, nodeId:header:value)
	 *   body - nodeId:body (nodeId:body)
	 */
	this.createNodeElement = function(node) {
		var nodeZone = document.createElement("table");
		var nodeZoneArr = Q.U.createTable(nodeZone, 2, 2);
		var valueZone = document.createElement("table");
		
		// Set id 一个完整节点包含以下4个区域header:0 -> flag, header:1 -> value及folder, body:0 -> link.jpg, body:1 -> children
		nodeZone.setAttribute("id", node.getUniqueId());
		nodeZoneArr[0][0].setAttribute("id", node.getUniqueId() + ":header:0");
		nodeZoneArr[0][1].setAttribute("id", node.getUniqueId() + ":header:1");
		nodeZoneArr[1][0].setAttribute("id", node.getUniqueId() + ":body:0");
		nodeZoneArr[1][1].setAttribute("id", node.getUniqueId() + ":body:1");
		
		nodeZoneArr[0][0].appendChild(this.createHeaderFlag(node, node.getUniqueId() + ":header:flag"));
		this.createLinkImage(node, nodeZoneArr[1][0]); // 节点之间的连接线
		
		// init header
		var hARR = Q.U.createTable(valueZone, 1, 2);
		hARR[0][0].appendChild(this.createHeaderImg(node, node.getUniqueId() + ":header:img"));
		hARR[0][1].appendChild(this.createHeaderValue(node, node.getUniqueId() + ":header:value"));
		
		// style		
		nodeZone.setAttribute("border", "0");
		nodeZone.setAttribute("cellspacing", "0");
		nodeZone.setAttribute("cellpadding", "0");
		nodeZone.cellSpacing = nodeZone.cellPadding = 0; // Fix IE bug
		valueZone.setAttribute("border", "0");
		valueZone.setAttribute("cellspacing", "0");
		valueZone.setAttribute("cellpadding", "0");
		valueZone.cellSpacing = valueZone.cellPadding = 0;
		
		// append
		nodeZoneArr[0][1].appendChild(valueZone);
		return nodeZone;
	}
	this.createHeaderFlag = function(node, flagId) {
		var flag = document.createElement("img");
		var src = this.getFlagSrc(node);
		var _self = this;
		flag.setAttribute("id", flagId);
		flag.setAttribute("src", src);
		flag.setAttribute("width", "16"); // 固定大小，否则在IE下，最后一个节点的Flag图标显示会异常。
		flag.setAttribute("height", "22");
		if (!node.isLeaf()) {
			flag.onclick = function() {
				_self.displayNode(node.getUniqueId());
			}
			flag.style.cursor = "pointer";
		}
		return flag;
	}
	this.createHeaderImg = function(node, imgId) {
		if (node.icon != null && node.icon != "") {
			var img = document.createElement("img");
			img.setAttribute("id", imgId);
			img.setAttribute("src", node.icon);
			return img;			
		} else if (this.srcImageDefault != "") {
			var img = document.createElement("img");
			img.setAttribute("id", imgId);
			img.setAttribute("src", this.srcImageDefault);
			return img;
		} else {
			return document.createElement("span");
		}
	}
	this.createHeaderValue = function(node, valueId) {
		var des = document.createElement("div");
		des.setAttribute("id", valueId);
		des.innerHTML = node.value;
		if (node.url != null && node.url != "") {
			var a = document.createElement("a");
			a.setAttribute("href", node.url);
			if (node.urlTarget != null && node.urlTarget != "") {
				a.setAttribute("target", node.urlTarget);
			}
			a.appendChild(des);
			return a;
		}
		return des;
	}
	// 节点之间的连接线
	this.createLinkImage = function(node, zone) {
		if (node.next != null) {
			zone.style.cssText = "background:url(" + this.srcLink + ") repeat-y;";
		}
	}
	// 根据节点状态获取节点Flag图标。
	this.getFlagSrc = function(node) {
		var src;
		if (node.isLeaf()) { // 叶节点
			src = (node.next != null ? this.srcLeafMiddle : this.srcLeafLast);
		} else { // Has children
			if (node.isOpened()) {
				src = (node.next != null ? this.srcOpenedMiddle : this.srcOpenedLast);
			} else {
				src = (node.next != null ? this.srcClosedMiddle : this.srcClosedLast);
			}
		}
		return src;
	}
	this.displayNode = function(uniqueId) {
		var _self = this;
		var currentNode = _self.nodes[uniqueId];
		// 如果节点未装载过子节点，则请求数据
		if (!currentNode.isLoaded()) {
			this.ajaxInvoke(currentNode, _self);
		}
		// 打开或关闭节点信息
		if (currentNode.isOpened()) {
			this.closeNode(currentNode);
		} else {
			this.openNode(currentNode);
		}
	}
	this.openNode = function(node) {
		// 更新节点状态
		var ele = Q.get(node.getUniqueId() + ":body:1");
		ele.style.display = "block";
		node.opened = true;
		// 更新节点图标
		this.updateNodeFlag(node);
	}
	this.closeNode = function(node) {
		// 更新节点状态
		var ele = Q.get(node.getUniqueId() + ":body:1");
		ele.style.display = "none";
		node.opened = false;
		this.updateNodeFlag(node);
	}
	// 隐藏节点的header(目前只用于root节点header的隐藏)
	this.hideNodeHeader = function(node) {
		var col1 = Q.get(node.getUniqueId() + ":header:0");
		var col2 = Q.get(node.getUniqueId() + ":header:1");
		col1.style.display = col2.style.display = "none";
	}
	this.updateNodeFlag = function(node) {
		var flag = Q.get(node.getUniqueId() + ":header:flag");
		flag.setAttribute("src", this.getFlagSrc(node));
	}
	this.ajaxInvoke = function(currentNode, _self) {
		Q.F.loading(true);
		var levelCount = currentNode.getLevel() + 1;
		var ajax = Q.F.Ajax.build(_self.ID_CLIENT);
		ajax.put("componentClass", _self.componentClass);
		ajax.put("listenerExp", _self.listenerExp);
		ajax.put("levelCount", levelCount);
		var pNode = currentNode;
		while (pNode != null) {
			ajax.put("id" + pNode.getLevel(), pNode.id);
			ajax.put("value" + pNode.getLevel(), pNode.value);
			ajax.put("leaf" + pNode.getLevel(), pNode.leaf);
			ajax.put("icon" + pNode.getLevel(), pNode.icon);
			ajax.put("url" + pNode.getLevel(), pNode.url);
			ajax.put("urlTarget" + pNode.getLevel(), pNode.urlTarget);
			pNode = pNode.parent;
		}
		var process = function() {
			// 将返回结果处理为node数组
			var nodes = _self.processResult(ajax.request.responseXML);
			// 清理当前节点的子节点，再将nodes添加到当前节点中作为子节点，在添加子节点时，子节点会产生唯一ID
			currentNode.clearChildren();
			for (var i = 0; i < nodes.length; i++) {
				currentNode.addChild(nodes[i]);
			}
			// 保存节点列表引用,这样可以直接通过节点的uniqueId直接快速找到节点，而不需要从root节点中一层一层寻找
			var children = currentNode.getChildren();
			if (children != null) {
				for (var i = 0; i < children.length; i++) {
					_self.nodes[children[i].getUniqueId()] = children[i];
				}
			}
			// 将节点显示到Html树中, 并标志currentNode为已装载
			_self.initChildren(currentNode, currentNode.getChildren());
			currentNode.loaded = true;
			Q.F.loading(false);
		}
		ajax.setProcess(process);
		ajax.get();
	}
	// 将Ajax请求的返回结果处理为Nodes数组返回,如果xml结果为空，则返回空数组
	this.processResult = function(responseXML) {
		var nodes = new Array();
		if (responseXML != null && responseXML.documentElement != null) {
			var doc = responseXML.documentElement;
			var nodeList = doc.getElementsByTagName("node");
			if (nodeList != null) {
				for (var i = 0; i < nodeList.length; i++) {
					var element = nodeList[i];
					var node = new Q.F.UITree.Tree.Node();
					node.id = element.getAttribute("id");
					node.value = element.getAttribute("value");
					node.leaf = element.getAttribute("leaf");
					node.icon = element.getAttribute("icon");
					node.url = element.getAttribute("url");
					node.urlTarget = element.getAttribute("urlTarget");
					node.leaf = (node.leaf == "true" ? true : false);	// 必须转换为boolean类型
					nodes[i] = node;
				}
			}			
		}
		return nodes;
	}
	this.init();
}

Q.F.UITree.Tree.Node = function() {
	// 用户指定的属性
	this.id = ""; 		// 节点ID(该id为用户从后台返回时指定的)
	this.value = ""; 	// 节点值
	this.icon = ""; 	// 图标地址
	this.url = ""; 		// 节点连接地址URL
	this.urlTarget = ""; 	// 节点打开连接的方式（默认当前窗口）
	
	this.uniqueId = null;	// 客户端唯一ID。必须设置的(在Node初始化时,用于渲染为节点的elementId)
	this.previous = null;	// 当前节点的同级节点的前一个节点
	this.next = null;		// 当前节点的同级节点的下一个节点
	this.parent = null;		// 父节点
	this.children = null; 	// 子节点(Array)
	this.leaf = null;
	this.opened = false;	// 是否打开的
	this.loaded = false;	// 表示是否已经装载过子节点
	
	// 判断是否为第一个节点
	this.isFirst = function() {
		return (this.previous == null);
	}
	// 判断是否为最后一个节点
	this.isLast = function() {
		return (this.next == null);
	}
	// 判断是否为叶节点，即没有子节点.
	this.isLeaf = function() {
		if (this.leaf != null) { // 不能单从children是否为空来判断
			return this.leaf;
		}
		return (this.children == null || this.children.length <= 0);
	}
	// 获取当前节点在同级节点中排第几,首节点为0,该值并不恒定，比如有可能删除了某个节点，则后面的节点将进级
	this.getOrder = function() {
		return (this.previous == null ? 0 : (this.previous.getOrder() + 1));
	}
	this.getId = function() {
		return this.id;
	}
	this.getUniqueId = function() {
		return this.uniqueId;
	}
	this.getChildren = function() {
		return this.children;
	}
	// 将子节点清空
	this.clearChildren = function() {
		this.children = null;
	}
	// 添加子节点:必须设定节点唯一ID，节点的父亲，Previous
	this.addChild = function(node) {
		if (this.children == null)
			this.children = new Array();
		node.uniqueId = this.getUniqueId() + ":" + this.children.length;
		node.parent = this;
		if (this.children.length > 0) {
			var lastNode = this.children[this.children.length - 1];
			lastNode.next = node;
			node.previous = lastNode;
		}
		this.children.push(node);
	}
	this.getLevel = function() {
		if (this.parent == null) {
			return 0;
		} else {
			return (this.parent.getLevel() + 1);
		}
	}
	this.isOpened = function() {
		return this.opened;
	}
	this.isLoaded = function() {
		return this.loaded;
	}
}